package com.nexus.plugin.amqp.proxy;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nexus.core.utils.SpringContextHolder;
import com.nexus.plugin.amqp.annotion.RabbitSender;
import com.nexus.plugin.amqp.template.NexusRabbitTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.cglib.proxy.InvocationHandler;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 消息队列发送代理实现
 *
 * @Date 2025/9/24 21:04
 * @Author luzhengning
 **/
public class RabbitSenderInvocationHandler implements InvocationHandler {

    private final Class<?> interfaceClass;
    private final NexusRabbitTemplate nexusRabbitTemplate;
    private final Map<Method, RabbitSender> methodCache = new ConcurrentHashMap<>();

    public RabbitSenderInvocationHandler(Class<?> interfaceClass) {
        this.interfaceClass = interfaceClass;
        this.nexusRabbitTemplate = SpringContextHolder.getBean(NexusRabbitTemplate.class);
        cacheMethodAnnotations();
    }

    private void cacheMethodAnnotations() {
        for (Method method : interfaceClass.getMethods()) {
            RabbitSender annotation = method.getAnnotation(RabbitSender.class);
            if (annotation != null) {
                methodCache.put(method, annotation);
            }
        }
    }

    /**
     * 消息发送处理
     * @Date 2025/9/26 16:57
     * @Author luzhengning
     **/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 检查是否是Object类的方法
        if (method.getDeclaringClass() == Object.class) {
            return false;
        }
        RabbitSender annotation = methodCache.get(method);
        if (annotation == null) {
            throw new UnsupportedOperationException("消息队列发送失败：" + method.getName() + "没有标注@RabbitSender");
        }
        // 验证参数
        if (args == null || args.length == 0) {
            throw new IllegalArgumentException(method.getName() + "，方法参数不能为空");
        }
        Object arg = args[0];
        Message rabbitMessage = null;
        //判断参数是不是Message类型
        if (arg instanceof Message) {
            rabbitMessage = (Message) arg;
        } else {
            rabbitMessage = buildMessage(arg, annotation);
        }
        // 发送消息
        nexusRabbitTemplate.convertAndSend(annotation.exchange(), annotation.routingKey(), rabbitMessage);
        return false;
    }

    /**
     * 构建发送消息
     *
     * @Date 2025/9/26 16:55
     * @Author luzhengning
     **/
    private Message buildMessage(Object payload, RabbitSender annotation) {
        MessageProperties properties = new MessageProperties();
        properties.setDeliveryMode(annotation.persistent() ?
                MessageDeliveryMode.PERSISTENT : MessageDeliveryMode.NON_PERSISTENT);
        properties.setTimestamp(new Date());
        //设置消息过期时间
        if(annotation.ttl() > 0) {
            properties.setExpiration(String.valueOf(annotation.ttl()*1000));
        }
        return new Message(serializePayload(payload), properties);
    }

    /**
     * json序列化消息
     *
     * @Date 2025/9/26 16:56
     * @Author luzhengning
     **/
    private byte[] serializePayload(Object payload) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsBytes(payload);
        } catch (Exception e) {
            throw new RuntimeException("Failed to serialize message", e);
        }
    }
}